package manager

import (
	"BlazeRider-backend/app/db"
	"BlazeRider-backend/app/models"
	"database/sql"
	"fmt"
	"log"
	"sort"
)

// manager/user_mysql_storage.go
type userMySQLStorage struct {
}

func newUserMySQLStorage() (*userMySQLStorage, error) {
	return &userMySQLStorage{}, nil
}

func (s *userMySQLStorage) InitializeUser(userID, userName, headImg string, level int) error {
	_, err := db.GetDB().Exec(`
		INSERT INTO users 
			(user_id, user_name, head_img, level, score, expire_at)
		VALUES 
			(?, ?, ?, ?, ?, DATE_ADD(CURRENT_TIMESTAMP, INTERVAL 30 DAY))
		ON DUPLICATE KEY UPDATE
			user_name = COALESCE(?, user_name),
			head_img = COALESCE(?, head_img),
			updated_at = CURRENT_TIMESTAMP
	`,
		userID, userName, headImg, level, 0, // 插入值
		userName, headImg) // 更新值参数

	if err != nil {
		return fmt.Errorf("failed to initialize user: %v", err)
	}
	return nil
}

// 获取用户信息
func (um *userMySQLStorage) GetUser(userID string) (*UserInfo, error) {
	var user UserInfo
	err := db.GetDB().QueryRow(`
		SELECT user_id, user_name, head_img, level, score
		FROM users
		WHERE user_id = ?
	`, userID).Scan(
		&user.UserID,
		&user.UserName,
		&user.HeadImg,
		&user.Level,
		&user.Score,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil, err
		}
		// 记录日志
		return nil, err
	}
	return &user, nil
}

// 更新用户积分（带事务示例）
func (um *userMySQLStorage) UpdateScore(userID string, delta int) error {
	tx, err := db.GetDB().Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	// 更新用户积分
	_, err = tx.Exec(`
		UPDATE users
		SET score = score + ?
		WHERE user_id = ?
	`, delta, userID)
	if err != nil {
		return err
	}

	// 插入积分变动记录
	_, err = tx.Exec(`
		INSERT INTO score_changes 
		(user_id, change_amount, reason)
		VALUES (?, ?, ?)
	`, userID, delta, "gift_reward")
	if err != nil {
		return err
	}

	return tx.Commit()
}

func (um *userMySQLStorage) SetUserScoreByLiveRoomResult() error {
	// 更新用户积分
	_, err := db.GetDB().Exec(`
		INSERT INTO users (user_id, user_name, head_img, score, mileage, jump_height)
			SELECT
				lrr.user_id ,
				ANY_VALUE ( u.user_name ) AS user_name,-- 随机取一个值（因主键依赖，实际唯一）
				ANY_VALUE ( u.head_img ) AS head_img,
				SUM(
				COALESCE ( lrr.get_score, 0 )) AS total_score,
				SUM(
				COALESCE ( lrr.mileage, 0 )) AS total_mileage,
				SUM(
				COALESCE ( lrr.jump_height, 0 )) AS total_jump_height 
			FROM
				live_room_result lrr
				left JOIN users u ON lrr.user_id = u.user_id 
			GROUP BY
				user_id
		ON DUPLICATE KEY UPDATE score = VALUES(score),
								mileage = VALUES(mileage),
								jump_height = VALUES(jump_height),
		                    	updated_at = CURRENT_TIMESTAMP;
	`)
	if err != nil {
		return err
	}
	return nil
}
func (um *userMySQLStorage) SetUserLevelByLevelSet(levelSetArr map[int]LevelSet) error {
	startScore := 0

	// 提取所有键并排序
	keys := make([]int, 0, len(levelSetArr))
	for k := range levelSetArr {
		keys = append(keys, k)
	}
	sort.Ints(keys) // 对键进行排序

	// 按排序后的键顺序处理每个 LevelSet
	for _, key := range keys {
		levelSetInfo := levelSetArr[key]
		_, err := db.GetDB().Exec(`
			update users set level = ? 
			        where score > ? and score <=  ?
		`, levelSetInfo.Level, startScore, levelSetInfo.UpperLimit)
		if err != nil {
			return err // 如果有错误，直接返回
		}
		startScore = levelSetInfo.UpperLimit
	}
	return nil // 如果没有错误，返回nil
}

func (um *userMySQLStorage) GetScoreRanks() ([]models.RankInfo, error) {
	// 构建查询语句
	query := fmt.Sprintf(`
		SELECT 
			  ROW_NUMBER() OVER (ORDER BY score DESC) AS ranking,
			  user_id,
			  user_name,
				head_img,
				level,
			  score
		FROM users
		ORDER BY score DESC
		LIMIT 50;
	`)

	// 准备查询参数
	args := make([]interface{}, 0, 0)

	// 查询数据
	rows, err := db.GetDB().Query(query, args...)
	if err != nil {
		log.Printf("Error querying GetScoreRanks error : %v", err)
		return nil, err
	}
	defer rows.Close()

	// 遍历查询结果
	var rankInfoList []models.RankInfo
	for rows.Next() {
		var record models.RankInfo
		if err := rows.Scan(
			&record.Index,
			&record.UserId,
			&record.UserName,
			&record.HeadImg,
			&record.Level,
			&record.Value,
		); err != nil {
			log.Printf("Error scanning score rank : %v", err)
			return nil, err
		}
		rankInfoList = append(rankInfoList, record)
	}

	// 检查是否查询到数据
	if len(rankInfoList) == 0 {
		log.Printf("No score rank found ")
		return nil, sql.ErrNoRows
	}

	return rankInfoList, nil
}

func (um *userMySQLStorage) GetMileageRanks() ([]models.RankInfo, error) {
	// 构建查询语句
	query := fmt.Sprintf(`
		SELECT 
			  ROW_NUMBER() OVER (ORDER BY mileage DESC) AS ranking,
			  user_id,
			  user_name,
				head_img,
				level,
			  mileage
		FROM users
		ORDER BY mileage DESC
		LIMIT 50;
	`)

	// 准备查询参数
	args := make([]interface{}, 0, 0)

	// 查询数据
	rows, err := db.GetDB().Query(query, args...)
	if err != nil {
		log.Printf("Error querying GetScoreRanks error : %v", err)
		return nil, err
	}
	defer rows.Close()

	// 遍历查询结果
	var rankInfoList []models.RankInfo
	for rows.Next() {
		var record models.RankInfo
		if err := rows.Scan(
			&record.Index,
			&record.UserId,
			&record.UserName,
			&record.HeadImg,
			&record.Level,
			&record.Value,
		); err != nil {
			log.Printf("Error scanning score rank : %v", err)
			return nil, err
		}
		rankInfoList = append(rankInfoList, record)
	}

	// 检查是否查询到数据
	if len(rankInfoList) == 0 {
		log.Printf("No score rank found ")
		return nil, sql.ErrNoRows
	}

	return rankInfoList, nil
}

func (um *userMySQLStorage) GetJumpHeightRanks() ([]models.RankInfo, error) {
	// 构建查询语句
	query := fmt.Sprintf(`
		SELECT 
			  ROW_NUMBER() OVER (ORDER BY jump_height DESC) AS ranking,
			  user_id,
			  user_name,
			  head_img,
			  level,
			  jump_height
		FROM users
		ORDER BY jump_height DESC
		LIMIT 50;
	`)

	// 准备查询参数
	args := make([]interface{}, 0, 0)

	// 查询数据
	rows, err := db.GetDB().Query(query, args...)
	if err != nil {
		log.Printf("Error querying GetScoreRanks error : %v", err)
		return nil, err
	}
	defer rows.Close()

	// 遍历查询结果
	var rankInfoList []models.RankInfo
	for rows.Next() {
		var record models.RankInfo
		if err := rows.Scan(
			&record.Index,
			&record.UserId,
			&record.UserName,
			&record.HeadImg,
			&record.Level,
			&record.FValue,
		); err != nil {
			log.Printf("Error scanning score rank : %v", err)
			return nil, err
		}
		rankInfoList = append(rankInfoList, record)
	}

	// 检查是否查询到数据
	if len(rankInfoList) == 0 {
		log.Printf("No score rank found ")
		return nil, sql.ErrNoRows
	}

	return rankInfoList, nil
}

func (um *userMySQLStorage) GetRanks() (*models.RankInfos, error) {
	var rankInfos models.RankInfos
	scoreRanks, err := um.GetScoreRanks()
	if err != nil {
		return nil, err
	}
	rankInfos.ScoreRank = scoreRanks

	// 获取里程排名
	mileageRanks, err := um.GetMileageRanks()
	if err != nil {
		return nil, err
	}
	rankInfos.MileageRank = mileageRanks

	// 获取跳跃高度排名
	jumpHeightRanks, err := um.GetJumpHeightRanks()
	if err != nil {
		return nil, err
	}
	rankInfos.JumpHeightRank = jumpHeightRanks

	return &rankInfos, nil
}

// 获取用户信息
func (um *userMySQLStorage) GetWorldRecords() (*models.WorldRecods, error) {
	var fastestSpeed, finishTime, finishTime1, finishTime2, jumpHeight, attackPower = 0, 0, 0, 0, float32(0.0), 0
	// 获取最快速度
	err := db.GetDB().QueryRow(`
		select MAX(fastest_speed) from live_room_result
	`).Scan(
		&fastestSpeed,
	)

	if err != nil {
		if err == sql.ErrNoRows {
		} else {
			// 记录日志
			fmt.Println("GetWorldRecords fastestSpeed sql error : ", err)
			//return nil, err
		}
	}

	// 获取最短完成时间 模式1
	err = db.GetDB().QueryRow(`
		select Min(finish_time) from live_room_result
			where finish_time > 0
	`).Scan(
		&finishTime,
	)

	if err != nil {
		if err == sql.ErrNoRows {
		} else {
			// 记录日志
			fmt.Println("GetWorldRecords finishTime sql error : ", err)
			//return nil, err
		}
	}

	// 获取最短完成时间 模式2
	err = db.GetDB().QueryRow(`
		select Min(finish_time1) from live_room_result
			where finish_time1 > 0
	`).Scan(
		&finishTime1,
	)

	if err != nil {
		if err == sql.ErrNoRows {
		} else {
			// 记录日志
			fmt.Println("GetWorldRecords finishTime1 sql error : ", err)
			//return nil, err
		}
	}

	// 获取最短完成时间 模式3
	err = db.GetDB().QueryRow(`
		select Min(finish_time2) from live_room_result
			where finish_time2 > 0
	`).Scan(
		&finishTime2,
	)

	if err != nil {
		if err == sql.ErrNoRows {
		} else {
			// 记录日志
			fmt.Println("GetWorldRecords finish_time2 sql error : ", err)
			//return nil, err
		}
	}

	// 最大高度
	err = db.GetDB().QueryRow(`
		select MAX(jump_height) from live_room_result
	`).Scan(
		&jumpHeight,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil, err
		}
		// 记录日志
		fmt.Println("GetWorldRecords jumpHeight sql error : ", err)
		//return nil, err
	}

	// 最强攻击
	err = db.GetDB().QueryRow(`
		select MAX(attack_power) from live_room_result
	`).Scan(
		&attackPower,
	)

	if err != nil {
		if err == sql.ErrNoRows {
			return nil, err
		}
		// 记录日志
		fmt.Println("GetWorldRecords attackPower sql error : ", err)
		//return nil, err
	}

	worldRecods := models.WorldRecods{
		FastestSpeed: fastestSpeed,
		FinishTime:   finishTime,
		FinishTime1:  finishTime1,
		FinishTime2:  finishTime2,
		JumpHeight:   jumpHeight,
		AttackPower:  attackPower,
	}
	return &worldRecods, nil
}
